﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.ServiceModel;
using System.Text;

namespace Wne.GlobalStorage
{
    // ПРИМЕЧАНИЕ. Команду "Переименовать" в меню "Рефакторинг" можно использовать для одновременного изменения имени класса "GlobalWcf" в коде, SVC-файле и файле конфигурации.
    // ПРИМЕЧАНИЕ. Чтобы запустить клиент проверки WCF для тестирования службы, выберите элементы GlobalWcf.svc или GlobalWcf.svc.cs в обозревателе решений и начните отладку.
    public class GlobalWcf : IGlobalWcf
    {

        private void SendMail(Guid guid, string password, string email)
        {
            var mail = new MailMessage("k01-224@mail.ru", email, "Перенос документа",
                    String.Format("Документ {0} успешно перенесен в хранилище! Держите пароль: {1}",
                        guid.ToString(), password));
            using (var sc = new SmtpClient("smtp.mail.ru", 25))
            {
                sc.EnableSsl = true;
                sc.DeliveryMethod = SmtpDeliveryMethod.Network;
                sc.UseDefaultCredentials = false;
                sc.Credentials = new NetworkCredential("k01-224@mail.ru", "k20102015");
                sc.Send(mail);
            }
        }
        char[, ,] arraySymb;
        const string chararr = @"abcdefghijklmnopqrstyvwxyz1234567890ABCDEFGHIJKLMNOPQRSTYVWXYZ";

        private void GenerateTable()
        {
            Random rnd = new Random(64);
            for (int i = 0; i < 64; i++)
            {
                for (int j = 0; j < 64; j++)
                {
                    for (int k = 0; k < 64; k++)
                    {
                        // генерим случайное число и по нему выбираем символ
                        arraySymb[i, j, k] = chararr[rnd.Next(chararr.Length)];
                    }
                }
            }
        }
        private string GeneratePassword(int Count)
        //формирует пароль длиной Count
        {
            string result = ""; // результат - готовый пароль
            arraySymb = new char[64, 64, 64];
            GenerateTable();

            // генератор случайных чисел
            Random rndgen = new Random();
            // int maxval = newsymb.Length;
            for (int i = 0; i < Count; i++)
            {
                // случайное число
                int idx1 = (rndgen.Next(63)) + 1;
                int idx2 = (rndgen.Next(63)) + 1;
                int idx3 = (rndgen.Next(30)) * 2;
                // получаем сивол из трёхмерного массива
                char rand = arraySymb[idx1, idx2, idx3];
                // записываем в буфер
                string buf = rand.ToString();
                // регистр симоволов, тоже случайно
                if (rndgen.Next(3) > 1)
                {
                    buf = buf.ToUpper();
                }
                // буфер помещаем в результирующую строку
                result += buf;
            }
            return result;
        }
        public void AddDocument(DocumentResponse input)
        {
            using (var context = new tpksStorageEntities())
            {
                context.Documents.Add(
                    new Documents
                    {
                        Id = input.Id,
                        Doc = input.Document,
                        AuthorEmail = input.AuthorEmail,
                    });
            }
        }
        public DocumentResponse GetDocument(Guid id, byte[] password)
        {
            using (var context = new tpksStorageEntities())
            {
                var document = context.Documents.FirstOrDefault(x => x.Id == id);
                if (document == null) return null;
                if (password.Where((t, i) => t != document.Password[i]).Any())
                {
                    return null;
                }
                return new DocumentResponse
                {
                    Id = document.Id,
                    Document = document.Doc,
                    AttachmentsGuid = document.Attachments.Select(x=>x.IdAttachment).ToList()
                };
            }
        }

        public AttachmentResponse GetAttachment(Guid id, byte[] password)
        {
            using (var context = new tpksStorageEntities())
            {
                var tmp = context.Attachments.First(x => x.IdAttachment == id);
                if (password.Where((t, i) => t != tmp.Documents.Password[i]).Any())
                {
                    return null;
                }
                return new AttachmentResponse
                {
                    Name = tmp.AttachmentName,
                    File = tmp.AttachmentBinary
                };
            }
        }

        public void AddAttachmentToDocument(AttachmentResponse attachment, Guid idDocument)
        {
            using (var context = new tpksStorageEntities())
            {
                var doc = context.Documents.First(x => x.Id == idDocument);
                doc.Attachments.Add(new Attachments
                {
                    IdAttachment = attachment.Id,
                    AttachmentBinary = attachment.File,
                    AttachmentName = attachment.Name
                });
                context.SaveChanges();
            }
        }

        public void FinishUploadDocument(Guid idDocument)
        {

            var pass = GeneratePassword(20);
            var passHash = MD5.Create().ComputeHash(Convert.FromBase64String(pass));
            using (var context = new tpksStorageEntities())
            {
                var doc = context.Documents.First(x => x.Id == idDocument);
                doc.Password = passHash;
                SendMail(idDocument, pass, doc.AuthorEmail);
                context.SaveChanges();
            }
        }
    }
}
